﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using MIC = Microsoft.IdentityModel.Claims;
using SSP = System.Security.Principal;
using CodeCamp.Infrastructure;
using CodeCamp.Infrastructure.Extensions;
using CodeCamp.Models.Shared;
using CodeCamp.Models.Test;
using RGoodSW.Logger.Interfaces;

namespace CodeCamp.Controllers
{
    public class TestController : ControllerBase
    {

        public TestController(IDefaultValueProvider defaultValueProvider, ILoggerExtended logger)
            : base(defaultValueProvider, logger)
        {
        }

        private void AddBasicClientInfo(List<ClientInfoViewModel.InfoItem> clientInfoList)
        {
            clientInfoList.Add(new ClientInfoViewModel.InfoItem
            {
                Name = "User Host Address",
                Value = this.Request.UserHostAddress
            });

            clientInfoList.Add(new ClientInfoViewModel.InfoItem
            {
                Name = "User Agent",
                Value = this.Request.UserAgent
            });
        }

        [CustomAuthorize]
        public ActionResult ClientInfo(string eventName, string id)
        {
            SetLoggerThreadContextData();
            using (CodeCampDataRepository ccdr = new CodeCampDataRepository())
            {
                var ccEvent = EventsHelper.GetEvent(ccdr, eventName, DefaultEventShortName);
                ClientInfoViewModel model = new ClientInfoViewModel();
                SetSharedEventProperties(ccEvent, model, ccdr, UserIsAuthenticated(this.User), false);

                AddBasicClientInfo(model.ClientInfo);

                StringBuilder logMsg = new StringBuilder();
                foreach (ClientInfoViewModel.InfoItem item in model.ClientInfo)
                {
                    logMsg.AppendFormat("{1}: {2}{0}",
                        Environment.NewLine,
                        item.Name,
                        item.Value);
                }
                if (!User.Identity.IsAuthenticated)
                {
                    logMsg.AppendFormat("NOTAuthenticated", Environment.NewLine);
                }
                else
                {
                    logMsg.AppendLine("IsAuthenticated");

                    MIC.ClaimsPrincipal claimsPrincipal = User as MIC.ClaimsPrincipal;
                    if (claimsPrincipal != null)
                    {
                        logMsg.AppendLine("IsClaimsPrincipal");
                        var claimsId = claimsPrincipal.Identity as MIC.IClaimsIdentity;
                        if (claimsId != null)
                        {
                            logMsg.AppendLine("Type - Issuer - Subject - Value");
                            foreach (MIC.Claim claim in claimsId.Claims)
                            {
                                logMsg.AppendFormat("{1} - {2} - {3} - {4} {0}",
                                    Environment.NewLine,
                                    claim.ClaimType,
                                    claim.Issuer,
                                    claim.Subject,
                                    claim.Value);
                            }
                        }
                    }
                }
                Logger.Info(logMsg.ToString());

                return View(model);
            }
        }

        private void AddContextInfo(List<ClientInfoViewModel.InfoItem> clientInfoList)
        {
            clientInfoList.Add(new ClientInfoViewModel.InfoItem
            {
                Name = "Machine Name",
                Value = Environment.MachineName
            });
        }

        private void AddClaims(SSP.IPrincipal principal, List<ClientInfoViewModel.InfoItem> clientInfoList)
        {
            string displayValue = string.Empty;
            bool authenticated = true;
            if (principal == null)
            {
                displayValue = "null";
            }
            else if (principal.Identity == null)
            {
                displayValue = ".Identity = null";
            }
            else if (!principal.Identity.IsAuthenticated)
            {
                displayValue = ".Identity NOT Authenticated.";
            }
            else if (principal.Identity.IsAuthenticated)
            {
                authenticated = true;
                displayValue = string.Format(".Identity \"{0}\" IsAuthenticated", principal.Identity.Name);
            }
            clientInfoList.Add(new ClientInfoViewModel.InfoItem
            {
                Name = "Current Time (UTC):",
                Value = string.Format("{0:yyyy-MM-dd  HH:mm:ss.fff}", DateTime.UtcNow)
            });
            clientInfoList.Add(new ClientInfoViewModel.InfoItem
            {
                Name = ".",
                Value = ""
            });
            clientInfoList.Add(new ClientInfoViewModel.InfoItem
            {
                Name = "Principal",
                Value = displayValue
            });
            if (authenticated)
            {
                MIC.ClaimsPrincipal claimsPrincipal = User as MIC.ClaimsPrincipal;
                if (claimsPrincipal != null)
                {
                    StringBuilder sbValue = new StringBuilder();
                    sbValue.AppendFormat("Identities.Count = {1}{0}",
                            Environment.NewLine,
                            claimsPrincipal.Identities.Count);
                    if (claimsPrincipal.Identities.Count >= 1)
                    {
                        sbValue.AppendFormat("Id[0].Name = \"{1}\"{0}",
                            Environment.NewLine,
                            claimsPrincipal.Identities[0].Name);
                    }

                    clientInfoList.Add(new ClientInfoViewModel.InfoItem
                    {
                        Name = "ClaimsPrincipal",
                        Value = sbValue.ToString()
                    });
                    var claimsId = claimsPrincipal.Identity as MIC.IClaimsIdentity;
                    if (claimsId != null)
                    {
                        clientInfoList.Add(new ClientInfoViewModel.InfoItem
                        {
                            Name = "Claim (Type)",
                            Value = "Issuer - Subject - Value"
                        });
                        foreach (MIC.Claim claim in claimsId.Claims)
                        {
                            clientInfoList.Add(new ClientInfoViewModel.InfoItem
                            {
                                Name = string.Format("{0}", claim.ClaimType),
                                Value = string.Format("{0} - {1} - {2}",
                                    claim.Issuer,
                                    claim.Subject,
                                    claim.Value)
                            });
                        }
                    }
                }
                clientInfoList.Add(new ClientInfoViewModel.InfoItem
                {
                    Name = ".",
                    Value = ""
                });
            }
        }

        private void AddCookies(HttpRequestBase request, List<ClientInfoViewModel.InfoItem> clientInfoList)
        {
            if ((request != null) && (request.Cookies != null))
            {
                clientInfoList.Add(new ClientInfoViewModel.InfoItem
                {
                    Name = string.Format("Cookies"),
                    Value = string.Format("Count = {0}", request.Cookies.Count)
                });

                for (int i = 0; i < request.Cookies.Count; i++)
                {
                    HttpCookie cookie = request.Cookies.Get(i);
                    clientInfoList.Add(new ClientInfoViewModel.InfoItem
                    {
                        Name = cookie.Name,
                        Value = string.Format("Domain={1}{0}Expires={2}{0}Path={3}{0}Len={4}{0}Value={5}{0}",
                            Environment.NewLine,
                            cookie.Domain,
                            ((cookie.Expires == DateTime.MinValue)?"":string.Format("{0:yyyy-MM-dd HH:mm}",cookie.Expires)),
                            cookie.Path,
                            (string.IsNullOrEmpty(cookie.Value)?"empty":cookie.Value.Length.ToString()),
                            (cookie.Value == null?"":cookie.Value.TruncateWithElipses(40)))
                    });
                }
            }
        }

        [CustomAuthorize(Roles=CCRoles.RoleNames.BigCheeze)]
        public ActionResult InsiderInfo(string eventName, string id)
        {
            SetLoggerThreadContextData();
            using (CodeCampDataRepository ccdr = new CodeCampDataRepository())
            {
                var ccEvent = EventsHelper.GetEvent(ccdr, eventName, DefaultEventShortName);
                ClientInfoInsiderViewModel model = new ClientInfoInsiderViewModel();
                SetSharedEventProperties(ccEvent, model, ccdr, UserIsAuthenticated(this.User), false);

                AddBasicClientInfo(model.ClientInfo);
                AddContextInfo(model.ClientInfo);
                AddClaims(this.User, model.ClientInfo);
                AddCookies(this.Request, model.ClientInfo);
                
                StringBuilder logMsg = new StringBuilder();
                logMsg.AppendLine("InsiderInfo");
                Logger.Info(logMsg.ToString());

                return View(model);
            }
        }

        public ActionResult ModeTest(string eventName, Nullable<int> id)
        {
            SetLoggerThreadContextData();
            using (CodeCampDataRepository ccdr = new CodeCampDataRepository())
            {
                var ccEvent = EventsHelper.GetEvent(ccdr, eventName, DefaultEventShortName);
                CommonViewModel model = new CommonViewModel();
                SetSharedEventProperties(ccEvent, model, ccdr, UserIsAuthenticated(this.User), false);
                ViewBag.Mode = string.Format("{0}", id);
                return View(model);
            }
        }

    }
}
